package cn.xo68.boot.auth.client.shiro;

import cn.xo68.boot.auth.client.properties.AuthProviderProperties;
import cn.xo68.boot.auth.client.service.OauthUserService;
import cn.xo68.boot.auth.core.domain.OAuth2AuthenticationToken;
import cn.xo68.boot.auth.core.domain.Oauth2Principal;
import cn.xo68.boot.auth.core.domain.OauthResource;
import cn.xo68.boot.auth.core.properties.OAuthResourceProperties;
import cn.xo68.core.util.StringTools;
import org.apache.oltu.oauth2.common.exception.OAuthProblemException;
import org.apache.oltu.oauth2.common.exception.OAuthSystemException;
import org.apache.shiro.authc.AuthenticationException;
import org.apache.shiro.authc.AuthenticationInfo;
import org.apache.shiro.authc.AuthenticationToken;
import org.apache.shiro.authc.SimpleAuthenticationInfo;
import org.apache.shiro.authz.AuthorizationInfo;
import org.apache.shiro.authz.SimpleAuthorizationInfo;
import org.apache.shiro.realm.AuthorizingRealm;
import org.apache.shiro.subject.PrincipalCollection;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Lazy;

import java.util.List;

/**
 * oauth2 服务端自定义认证实现
 * @author wuxie
 * @date 2018-8-5
 */
public class OAuth2ServerAuthorizingRealm extends AuthorizingRealm {

    private AuthProviderProperties authProviderProperties;
    private OAuthResourceProperties oAuthResourceProperties;

    @SuppressWarnings("SpringJavaInjectionPointsAutowiringInspection")
    @Lazy
    @Autowired
    private OauthUserService oauthUserService;


    public void setAuthProviderProperties(AuthProviderProperties authProviderProperties) {
        this.authProviderProperties = authProviderProperties;
    }

    public void setoAuthResourceProperties(OAuthResourceProperties oAuthResourceProperties) {
        this.oAuthResourceProperties = oAuthResourceProperties;
    }

    @Override
    public boolean supports(AuthenticationToken token) {
        //表示此Realm支持:UsernamePasswordToken,OAuth2AuthenticationToken
        return token instanceof OAuth2AuthenticationToken;
    }

    @Override
    protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {
        Object obj=  principals.getPrimaryPrincipal();
        final SimpleAuthorizationInfo authorizationInfo = new SimpleAuthorizationInfo();
        if(obj!=null && obj instanceof Oauth2Principal ){
            Oauth2Principal oauth2Principal=(Oauth2Principal)obj;
            if(oauth2Principal.getRoles()!=null && !oauth2Principal.getRoles().isEmpty()){
                authorizationInfo.addRoles(oauth2Principal.getRoles());
            }

            try {
                List<OauthResource> oauthResources=oauthUserService.getResources(oauth2Principal.getAccessToken());
                if(oauthResources.size()>0){
                    oauthResources.forEach(oauthResource -> {
                        if(StringTools.isNotEmpty(oauthResource.getPermission())){
                            authorizationInfo.addStringPermission(oauthResource.getPermission());
                        }
                    });

                }
            } catch (OAuthProblemException e) {
                e.printStackTrace();
            } catch (OAuthSystemException e) {
                e.printStackTrace();
            }
        }
        //authorizationInfo.addStringPermission("sys:info");
        return authorizationInfo;
    }

    @Override
    protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {
        OAuth2AuthenticationToken oAuth2Token = (OAuth2AuthenticationToken) token;
        Oauth2Principal oauth2Principal = oAuth2Token.getPrincipal();
        if(oauth2Principal==null){
            throw new AuthenticationException("请求不合法,errorCode:001");
        }

        try {
            oauth2Principal=oauthUserService.getPrincipal(oAuth2Token.getCredentials());
        } catch (OAuthProblemException e) {
            e.printStackTrace();
            throw new AuthenticationException("请求不合法,errorCode:004");
        } catch (OAuthSystemException e) {
            e.printStackTrace();
            throw new AuthenticationException("请求不合法,errorCode:005");
        }
        if(oauth2Principal==null){
            throw new AuthenticationException("请求不合法,errorCode:003");
        }

        SimpleAuthenticationInfo authenticationInfo =
                new SimpleAuthenticationInfo(oauth2Principal, oAuth2Token.getCredentials(), getName());
        return authenticationInfo;
    }


}